/**
 * Libre IM Server
 * autor:   Libre
 * email:   libre@aliyun.com
 * data:    16/4/12
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "event2/event.h"
#include "event2/listener.h"
#include "event2/buffer.h"
#include "event2/bufferevent.h"
#include "event2/util.h"

#include "opt.h"
#include "db_redis.h"
#include "package.h"
#include "receive.h"
#include "pop_message.h"
#include "pop_group_message.h"
#include "pop_swap_message.h"
#include "pop_save_message.h"

void bevErrorCB(struct bufferevent *bev, short events, void *ctx){
    //这将自动close套接字和free读写缓冲区
    evutil_socket_t fd;
    fd = bufferevent_getfd(bev);
    close(fd);
    bufferevent_free(bev);
}
void bevWriteCB(struct bufferevent *bev, void *ctx){
    //printf("%s\n", "进入了Write回调");
}
void bevReadCB(struct bufferevent *bev, void *ctx){
    /* 循环读取bufferevent中的数据 */
    char package_buff[PACKAGE_BUFF_MAX_LEN];
    while(1){
        /* 清空包长缓冲 */
        memset(package_buff,0x00,PACKAGE_BUFF_MAX_LEN);

        /* 从bufferevent缓冲池中读取4字节数据 */
        size_t ret = bufferevent_read(bev,package_buff,4);
        /* 如果bufferevent缓冲池中没有数据则跳出循环 */
        if(ret < 4) break;

        /* 转换网络字节序的到包长 如果超出每个包最大限制视为无效包 */
        uint32_t net_package_len;
        memcpy(&net_package_len,package_buff,4);
        size_t package_len = ntohl(net_package_len);
        if(package_len > PACKAGE_BUFF_MAX_LEN || package_len < PACKAGE_HEAD_LEN){
            continue;
        }

        /* 读取整个包内容 */
        size_t tmp_len = package_len - 4;
        size_t ret_package_buff_len = bufferevent_read(bev,package_buff + 4,tmp_len);
        if(ret_package_buff_len < tmp_len){
            continue;
        }

        /* 调度协议命令 */
        receive_buff(bev,package_buff);
    }
}
void onAccept(struct evconnlistener *listener,evutil_socket_t fd,struct sockaddr *addr,int len, void *ptr){
    struct event_base *evBase = evconnlistener_get_base(listener);
    //设置socket为非阻塞
    evutil_make_socket_nonblocking(fd);
    //添加读写事件回调
    struct bufferevent *bev = bufferevent_socket_new(evBase,fd,BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev,bevReadCB,bevWriteCB,bevErrorCB,NULL);
    bufferevent_enable(bev,EV_READ);
}
//int main(int argc, char *argv[], char *envp[]){
int main(){
    libreim_settings_encrypt_key = "abcdefghijklmnop";
    libreim_settings_listen = "10.0.2.2";
    libreim_settings_port = 9999;
    libreim_settings_redis_ip = "10.0.0.5";
    libreim_settings_redis_local_ip = "127.0.0.1";
    libreim_settings_mongodb_ip = "10.0.0.5";
    libreim_settings_mongodb_dbname = "libreim";
    libreim_settings_mongodb_collname = "message";
    libreim_settings_redis_port = 6379;
    libreim_settings_heartbeat_timeout = 15;
    libreim_settings_send_max_threads = 4;

    /* 初始化Redis连接池 */
    init_redis_pool();

//    //初始化libevent的base
    struct event_base *evBase;
    evBase = event_base_new();

    //声明服务器网络地址结构体
    struct sockaddr_in sin;
    //初始化
    memset(&sin,0,sizeof(sin));
    //附值
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    sin.sin_port = htons(libreim_settings_port);

    //创建监听Socket
    struct evconnlistener *listener;
    listener = evconnlistener_new_bind(
            evBase,onAccept,
            NULL,
            LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
            -1,
            (struct sockaddr *)&sin,
            sizeof(sin));


    //初始化消息订阅线程
    init_pop_message_thread();
    init_pop_group_message_thread();
    init_pop_swap_message_thread();
    init_pop_save_message_thread();

    //print_log("%s %s\n", SYSLOG_SUCCESS , "服务器开始监听...!");
    //循环事件
    event_base_dispatch(evBase);
    evconnlistener_free(listener);
    event_base_free(evBase);
    return 0;
}
